// 计步器组件
import React from 'react'

// 职能单一，只提供了一些常见的 数据类型，用于做类型校验
import ReactTypes from 'prop-types'
export default class Counter extends React.Component{
    constructor(props){
        super(props)
        // console.log(this.props)

        //初始化组件的私有状态，保存的是组件的私有数据
        this.state = {
            msg:'hello world',
            count:props.initCount //将外界传递过来的数据，传递给count属性

        }
    }




    /** 
     * 在封装一个组件的时候，组件内部肯定有一些数据是必须的，
     * 即使用户没有传递一些相关的启动参数，
     * 这个时候组件内部要给定一个默认值
     * */

    /**
     * 组件设置默认值
     * 在React组件中，使用defaultProps属性，来设置组件的默认属性值
     *  */ 
    static defaultProps = {
        initCount:0 //如果外界没有传递，则显示此处默认值为0
    } 

    /**
     * propTypes对象，可以把外界传递过来的属性，进行类型校验
     * 如果要为传递过来的属性校验，需要用到react提供的第三方包，叫做prop-types
     * prop-types包v.15.x之前并没有单独抽离出来，在这之后，官方把类型校验的模块，单独抽离出来为一个包，叫做prop-types
     * 运行cnpm i prop-types -S
     * 
    */
   static propTypes = {
        initCount:ReactTypes.number //规定传递给子组件的数据类型
   }
    



   /**
    * 
    * 组件将要挂载到页面上的时候执行，
    * 此时虚拟DOM尚未开始创建
    * componentWillMount 相当于 Vue 中的 created 生命周期函数
    * 
   */
   componentWillMount(){ 

        // 输出null 因为此时虚拟DOM尚未开始渲染
        // console.log(document.getElementById('myh3')) 

        //属性、状态、自定义函数可以获取
        // console.log(this.props.initCount);
        // console.log(this.state.msg)
        // this.myFunc()

   }




   //虚拟DOM创建阶段
    render(){
        //在return之前，虚拟DOM还没有开始创建
        return <div>
            <h1>这是 Counter 组件</h1>
            <input id="btn" type="button" value="+1" onClick={this.increment}/>
            <hr/>
            <h3 id="myh3" ref="h3">当前的数量：{this.state.count}</h3>
        </div>
        //在return之后，虚拟DOM创建好了，但是仍未挂载到真正的页面中
    }




    /**
     * 组件挂载到页面上之后，会进入这个生命周期函数，此时页面上已经有可见的DOM元素了
     * 如果我们想操作DOM元素，最早只能在componentDidMount中进行
     * componentDidMount 相当于 Vue 中的 mounted 生命周期函数
     * 执行完成之后，组件就进入了运行中的状态
     * 故此该函数是创建阶段的最后一个函数
     * 
     * */
    componentDidMount(){
        // console.log(document.getElementById('myh3'))
        
        // 不推荐此种操作方式
        // document.getElementById('btn').onclick = () => {
        //     this.setState({
        //         count:this.state.count+1
        //     })
        // }
    }

    increment = ()=>{
        this.setState({
            count:this.state.count+1
        })
    }


    /**
     * 此刻组件已经进入运行阶段，该生命周期函数用来判断组件是否需要更新
     * 该函数返回一个bool值
     * 返回false state状态数据会变化，但是页面不会触发更新
     * 
     * */
    shouldComponentUpdate(nextProps,nextState){

        /**
         * 此处的属性值为上一次的值，也就是更新前的旧值，并不是当前最新的值
         * 最新的值，必须通过该函数的参数 nextState 获取
         * */

        // console.log('旧值:'+this.state.count +'--------新值：'+nextState.count)      
        // return nextState.count%2 === 0 ? true : false

        return true
    }

    /**
     * 组件将要更新，进入这个函数时，
     * 此时内存中的虚拟DOM仍然是旧的，
     * 页面上的DOM元素也是旧的
    */
    componentWillUpdate(){
        //此时页面上的DOM元素还是旧的！！！
        // console.log(document.getElementById('myh3').innerHTML);//旧值
        console.log(this.refs.h3.innerHTML);
        
        
    }

    // 此处会再次调用render函数，然后进入完成更新的函数里去

    /**
     * 组件完成了更新
     * 此刻state中的数据、虚拟DOM、页面上的DOM都已经是最新的
     * 
    */
    componentDidUpdate(){

    }




    myFunc(){
        console.log('自己的测试函数,与生命周期函数无关')
    }
}